﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using CoreProcess.FileStorageScan;
using CoreProcess.Resources;
using CoreProcess.Utility;


namespace CoreProcess
{
    public class ResourceScan
    {
        public Object ScanResource(string basePath)
        {

            var fileItems =
                new List<FileItem>();
            //Two Ex List is ugly
            IList<ScanExceptionObj> scanFileExList = new List<ScanExceptionObj>();
            IList<ScanExceptionObj> scanDirExList =
                 FileStorageScan
                    .FileStorageScan.Scan(basePath,
                                        (filePath) => FileAction(filePath, ref scanFileExList, ref fileItems));

            IList<ScanExceptionObj> scanExceptionObjs = scanDirExList.Concat(scanFileExList).ToList();

            //Storage Data Module (XML)
            var rootName =
                GetPathLastNode(basePath);
            new XmlSerialize<ResourceRoot>().ToXmlFile(new ResourceRoot()
                                                        {
                                                            RootName = rootName,
                                                            Items = fileItems
                                                        }
                                                        ,rootName);

            return new
            {
                scanResult = "",
                exResult = scanExceptionObjs
            };
        }

        private void FileAction(string filePath, ref IList<ScanExceptionObj> exList, ref List<FileItem> fileObjects)
        {
            FileStream fileStream = null;
            try
            {
                //Get File Instance
                var fileInfo = new FileInfo(filePath);
                Console.WriteLine(filePath);//自fd动
                //Check
                if (!fileInfo.Exists)
                    return;
                
                //MD5
                string md5Str;
                byte[] md5Hash;
                using (fileStream =
                    fileInfo.OpenRead())
                {
                    var md5 = new Md5(fileStream);
                    md5Str =
                        md5.GetHashHexString();
                    md5Hash = md5.GetHash();
                }   
               
                //Create Property
                fileObjects.Add(new FileItem()//同名自动包装
                {
                    FileName = fileInfo.Name,
                    FilePath = fileInfo.FullName,
                    FileType = fileInfo.Extension,//.Replace(".",""),
                    FileLocation = fileInfo.DirectoryName,
                    FileCreateTime = fileInfo.CreationTime.ToString(CultureInfo.InvariantCulture),
                    FileAccessTime = fileInfo.LastAccessTime.ToString(CultureInfo.InvariantCulture),
                    FileWriteTime = fileInfo.LastWriteTime.ToString(CultureInfo.InvariantCulture),
                    FileSize = fileInfo.Length,
                    Md5 = md5Hash.ToList(),
                    Md5Hexstr = md5Str
                });
            }
            catch (Exception ex)
            {

                exList.Add(new ScanExceptionObj()
                {
                    ScanEx = ex,
                    ScanPath = filePath
                });
            }
            finally
            {
                if(fileStream != null)
                    fileStream.Close();
            }

        }

        #region Common Func

        private string GetPathLastNode(string path)
        {
            if (string.IsNullOrEmpty(path))
                return "";

            return path.Substring(path.LastIndexOf('\\')+1); ;
        }

        #endregion


        private void Test()
        {

            //var ff = new Func<string, int>((string x) =>
            //{
            //    const int t1 = 1;
            //    const int t2 = 2;
            //    return t1 + t2;
            //});

            //var f2 = new Func<int>(() => 2 + 2);
            //Action<string> ac = new Action<string>();
        }

    }



   
}
